package event

import "sync"

// EventBus 事件总线对象
type EventBus struct {
	Subscribers map[string]EventChanSlice
	mutex          sync.RWMutex
}

// Publish 发布事件
func (bus *EventBus) Publish(topic string, data interface{}) {
	bus.mutex.RLock()
	if chs, found := bus.Subscribers[topic]; found {
		channels := append(EventChanSlice{}, chs...)

		go func(data Event, dataChannelSlices EventChanSlice) {
			for _, ch := range dataChannelSlices {
				ch <- data
			}
		}(*NewEvent(topic, data), channels)
	}
	bus.mutex.RUnlock()
}

// Subscribe 订阅事件
func (bus *EventBus) Subscribe(topic string, ch EventChan) {
	bus.mutex.Lock()
	if prev, found := bus.Subscribers[topic]; found {
		bus.Subscribers[topic] = append(prev, ch)
	} else {
		bus.Subscribers[topic] = append(EventChanSlice{}, ch)
	}
	bus.mutex.Unlock()
}

// NewEventBus 新建事件总线
func NewEventBus() *EventBus {
	return &EventBus{
		Subscribers: map[string]EventChanSlice{},
	}
}
